#ifndef GCOMPILER_HEADER_GLEXER_H
#define GCOMPILER_HEADER_GLEXER_H


//---------------------------------------------------------
//	Lexer
//---------------------------------------------------------

// Selection include Sequence :
// Selection::first == Sequence::first, confusion!!!
// Selection include Pharse:
// Multiple1::type == Multiple2::type, confusion!!!
// Multiple::type == Sequence::first, confusion!!!
// Sequence include Multiple:
// Multiple::type == Sequence::next by Pharse, confusion!!!

#define STATIC_ASSERT(check)
#define STATIC_WARNING(text)

namespace GLexer
{
	//---------------------------------------------------------
	//	Parser context.
	class ParserContext
	{
	public:
		struct RawToken
		{
			RawToken():head(0), tail(0){;}
			const char * head;
			const char * tail;
		};
	public:
		RawToken		 token;
		ParserContext *  lleaf;
		ParserContext *  rleaf;
		int stack[4096];
		int * current_top;

	public:
		ParserContext():lleaf(0), rleaf(0) 
		{
		}
		virtual ~ParserContext() {;}
	public:
		void * prepare()
		{
			return current_top;
		}

		bool rollback(void * session)
		{
	//		this->current_top = (int*)session;
			return true;
		}

		bool commit(void * session)
		{
	//		session - current
			return true;
		}
	};


	//---------------------------------------------------------
	// Default Reducer
	template<typename T, typename TC> struct Reducer
	{
		static bool reduce(ParserContext *, TC *, TC *)
		{
			//cout<<"default reducer:"<<typeid(T).name()<<endl;
			return true; 
		}
	};


	//---------------------------------------------------------
	template<typename T, typename TC> bool dispose(ParserContext * context, TC * begin, TC * end)
	{
		void * session = context->prepare();
		if (Reducer<T, TC>::reduce(context, begin, end))
		{
			context->commit(session);
			return true;
		}
		else
		{
			context->rollback(session);
			return false;
		}
	}

//=================================================================================================================	
//=================================================================================================================	
//=================================================================================================================	
//=================================================================================================================	

	enum {
		NullFlow,
		TokenFlow,
		SelectionFlow,
		SequenceFlow,
		MultipleFlow,
		InclusionFlow,
		ExclusionFlow,
		OptionalFlow,
		OneOrMoreFlow,
		RecursiveFlow
	};

	template <typename T, typename E>
	struct IsInFirstSet
	{
		enum { ResultValue = IsInFirstSet<T::FirstSet, E>::ResultValue };
	};

	template <typename E>
	struct IsInFirstSet<E, E>
	{
		enum { ResultValue = true };
	};

	template <typename E>
	struct IsInFirstSet<void, E>
	{
		enum { ResultValue = false };
	};

	template <typename T>
	struct IsInFirstSet<T, void>
	{
		STATIC_ASSERT(false);
		enum { ResultValue = false };
	};

	template <>
	struct IsInFirstSet<void, void>
	{
		STATIC_ASSERT(false);
		enum { ResultValue = false };
	};


	template <typename Flow, int FlowType>
	struct RefactFlow
	{
		typedef Flow ResultFlow;
	};


	template <typename Flow, Flow::FlowType>
	struct RefactFlow<Flow, SelectionFlow>
	{
		if IsInFirstSet<Flow::FirstSet, Flow>
			typedef 
	}
		


	//=========================================================
	//	Token
	//=========================================================


	//---------------------------------------------------------
	//	Token
	template <typename  N1, typename N2 = void, typename N3 = void, typename N4 = void,
		typename N5 = void, typename N6 = void, typename N7 = void, typename N8 = void,
		typename N9 = void, typename N10= void, typename N11= void, typename N12= void,
		typename N13= void, typename N14= void, typename N15= void, typename N16= void,
		typename N17= void, typename N18= void, typename N19= void, typename N20= void,
		typename N21= void, typename N22= void, typename N23= void, typename N24= void,
		typename N25= void, typename N26= void, typename N27= void, typename N28= void,
		typename N29= void, typename N30= void, typename N31= void, typename N32= void>
	struct Token
	{
		enum { FlowType = TokenFlow };

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			return N1::match<TC>(current, next)
				&& Token<
					N2 , N3 , N4 , N5 , N6 , N7 , N8 , N9 ,
					N10, N11, N12, N13, N14, N15, N16, N17,
					N18, N19, N20, N21, N22, N23, N24, N25,
					N26, N27, M28, N29, N30, N31, N32, void
				>::shift<TC>(*next, next);
		}

		template<typename TC> static bool shift(ParserContext *, TC * current, TC ** next)
		{
			return N1::match<TC>(current, next)
				&& Token<
					N2 , N3 , N4 , N5 , N6 , N7 , N8 , N9 ,
					N10, N11, N12, N13, N14, N15, N16, N17,
					N18, N19, N20, N21, N22, N23, N24, N25,
					N26, N27, M28, N29, N30, N31, N32, void
				>::shift<TC>(*next, next);
		}
	};

	template <typename N>
	struct Token <
		   N, void, void, void, void, void, void, void,
		void, void, void, void, void, void, void, void,
		void, void, void, void, void, void, void, void,
		void, void, void, void, void, void, void, void>
	{
		enum { FlowType = TokenFlow };

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			return N::match<TC>(current, next);
		}

		template<typename TC> static bool shift(ParserContext *, TC * current, TC ** next)
		{
			return N::match<TC>(current, next);
		}
	};


	//---------------------------------------------------------
	// NullToken
	struct NullToken
	{
		enum { FlowType = NullFlow };

		template<typename TC> static bool shift(TC *, TC **)
		{
			return true; 
		}

		template<typename TC> static bool shift(ParserContext *, TC *, TC **)
		{
			return true; 
		}
	};

	//=========================================================
	//	Flows
	//=========================================================

	//---------------------------------------------------------
	//	Multiple
	template<typename E, unsigned int limits = 0>
	struct Multiple
	{
		enum { FlowType = MultipleFlow };

		typedef E FirstSet;

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);

			for (unsigned int i = 0; i < limits; i++)
			{
				if (!FirstSet::shift<TC>(*next, next))
				{
					return false;
				}
			}
			return true;
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			TC * temp = current;
			for (unsigned int i = 0; i < limits; i++)
			{
				if (FirstSet::shift<TC>(context, temp, next) && dispose<FirstSet, TC>(context, temp, *next))
				{
					temp = *next;
				}
				else 
				{
					*next = current;	//rewind
					return false;
				}
			}
			return true;
		}
	};

	template<typename E> 
	struct Multiple<E, 1>
	{
		enum { FlowType = MultipleFlow };

		typedef E FirstSet;

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(current, next);
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current, *next);
		}
	};

	// no limits
	template<typename E>
	struct Multiple<E, 0>
	{
		enum { FlowType = MultipleFlow };

		typedef E FirstSet;

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);
			while (FirstSet::shift<TC>(current, next)) 
			{
				current = *next;
			}
			*next = current;	//rewind
			return true;
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			while (FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current, *next))
			{
				current = *next;
			}
			*next = current;	//rewind
			return true;
		}
	};

	//---------------------------------------------------------
	// Sequence
	template <typename  E1, typename E2 = void, typename E3 = void, typename E4 = void,
		typename E5 = void, typename E6 = void, typename E7 = void, typename E8 = void,
		typename E9 = void, typename E10= void, typename E11= void, typename E12= void,
		typename E13= void, typename E14= void, typename E15= void, typename E16= void,
		typename E17= void, typename E18= void, typename E19= void, typename E20= void,
		typename E21= void, typename E22= void, typename E23= void, typename E24= void,
		typename E25= void, typename E26= void, typename E27= void, typename E28= void,
		typename E29= void, typename E30= void, typename E31= void, typename E32= void>
	struct Sequence
	{
		enum { FlowType = SequenceFlow };

		typedef E1 FirstSet;
		typedef Sequence<
			E2 , E3 , E4 , E5 , E6 , E7 , E8 , E9 , E10, E11, E12, E13, E14, E15, E16, E17,
			E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, void
		> FollowSet;
		
		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(current, next) && FollowSet::shift<TC>(*next, next);
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			if (FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current, *next))
			{
				return FollowSet::shift<TC>(context, *next, next);
			}
			return false;
		}
	};

	template <typename E>
	struct Sequence <
		   E, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void,
		void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
	{
		enum { FlowType = SequenceFlow };

		typedef E FirstSet;

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(current, next);
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current, *next);
		}
	};

	//---------------------------------------------------------
	// Selection
	template <typename E1, typename E2, typename E3 = void, typename E4 = void,
		typename E5 = void, typename E6 = void, typename E7 = void,	typename E8 = void,
		typename E9 = void, typename E10= void,	typename E11= void,	typename E12= void,
		typename E13= void, typename E14= void, typename E15= void,	typename E16= void,
		typename E17= void, typename E18= void, typename E19= void, typename E20= void,
		typename E21= void, typename E22= void, typename E23= void, typename E24= void,
		typename E25= void, typename E26= void, typename E27= void, typename E28= void,
		typename E29= void, typename E30= void, typename E31= void, typename E32= void>
	struct Selection
	{
		enum { FlowType = SelectionFlow };

		typedef E1 FirstSet;
		typedef Selection
		<
			E2 , E3 , E4 , E5 , E6 , E7 , E8 , E9 , E10, E11, E12, E13, E14, E15, E16, E17,
			E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, void
		> FollowSet;

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(current, next) || FollowSet::shift<TC>(current, next);
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			if ((FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current,*next)))
			{
				return true;
			}
			else
			{
				*next = current;	//rewind
				return FollowSet::shift<TC>(context, current, next);
			}
		}
	};

	template <typename E>
	struct Selection <
		E1  , E2  , void, void, void, void, void, void, void, void, void, void, void, void, void, void,
		void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
	{
		enum { FlowType = SelectionFlow };

		typedef E1 FirstSet;
		typedef E2 FollowSet;

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(current, next) || FollowSet::shift<TC>(current, next);
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current, *next);
			assert(current == *next);
			if ((FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current,*next)))
			{
				return true;
			}
			else
			{
				*next = current;	//rewind
				return FollowSet::shift<TC>(context, current, next);
			}
		}
	};

	
	//---------------------------------------------------------
	// Exclusion
	template <typename E>
	struct Exclusion
	{
		enum { FlowType = ExclusionFlow };

		typedef E FirstSet;

		template<typename TC> static bool shift(TC * current, TC **)
		{
			TC * temp = current;
			return !FirstSet::shift<TC>(current, &temp);
		}

		template<typename TC> static bool shift(ParserContext *, TC * current, TC **)
		{
			TC * temp = current;
			return !FirstSet::shift<TC>(current, &temp);
		}
	};

	//---------------------------------------------------------
	// Inclusion
	template <typename E>
	struct Inclusion
	{
		enum { FlowType = InclusionFlow };

		typedef E FirstSet;

		template<typename TC> static bool shift(TC * current, TC **)
		{
			TC * temp = current;
			return FirstSet::shift<TC>(current, &temp);
		}

		template<typename TC> static bool shift(ParserContext *, TC * current, TC **)
		{
			TC * temp = current;
			return FirstSet::shift<TC>(current, &temp);
		}
	};

	//---------------------------------------------------------
	// Optional, none or one element
	template<typename E>
	struct Optional
	{
		enum { FlowType = OptionalFlow };

		typedef E FirstSet;

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);
			if (!FirstSet::shift<TC>(current, next))
			{
				*next = current;
			}
			return true;
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			if (!(FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current, *next)))
			{
				*next = current;	//rewind
			}
			return true;
		}
	};

	//---------------------------------------------------------
	// at least one element
	template<typename E>
	struct OneOrMore
	{
		enum { FlowType = OneOrMoreFlow };

		typedef E FirstSet;
		typedef Multiple<E> FollowSet;

		template<typename TC> static bool shift(TC * current, TC ** next)
		{
			assert(current == *next);
			return FirstSet::shift<TC>(current, next) && FollowSet::shift<TC>(*next, next);
		}

		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)
		{
			assert(current == *next);
			if (FirstSet::shift<TC>(context, current, next) && dispose<FirstSet, TC>(context, current, *next))
			{
				return FollowSet::shift<TC>(context, *next, next);
			}
			return false;
		}
	};


	//---------------------------------------------------------
	// Helper template class
	template <typename T>
	struct MakeParser
	{
		template <typename TC> static bool parse(TC * current, TC ** next)
		{
			assert(current != 0); assert(next != 0);
			*next = current;
			return T::shift<TC>(current, next);
		}

		template <typename TC> static bool parse(ParserContext * context, TC * current, TC ** next)
		{
			assert(context != 0); assert(current != 0); assert(next != 0);
			*next = current;
			return T::shift<TC>(context, current, next) && dispose<T, TC>(context, current, *next);
		}
	};

	//---------------------------------------------------------
	// Helper macro used to declare recursive flow
#	define PREPARE_RECURSIVE(rc) struct rc
#	define BEGIN_RECURSIVE(rc) struct rc { typedef
#	define END_RECURSIVE																			\
		HeadFlow;																					\
		template<typename TC> static bool shift(TC * current, TC ** next)							\
		{ return HeadFlow::shift<TC>(current, next); }												\
		template<typename TC> static bool shift(ParserContext * context, TC * current, TC ** next)	\
		{ return HeadFlow::shift<TC>(context, current, next); }										\
	};

#	define BEGIN_REDUCER(tp)																\
		template<typename TC> struct Reducer<tp, TC> {									\
			static bool reduce(ParserContext * context, TC * begin, TC * end) {			\
				(void)context; (void)begin; (void)end;	// disable warning.
#	define END_REDUCER	}};

#	define BEGIN_NOTATION(nt) struct nt { template <typename TC> static bool match(TC * code, TC ** next) {
#	define END_NOTATION	}};

}	//end namespace GLexer

#endif	//ifndef GCOMPILER_HEADER_GLEXER_H

